#pragma once
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <process.h>
#include <io.h>
#include <math.h>
#include <string.h>
#include <Windows.h>
#include <time.h>
#define SYMCOUNT 0x100

typedef struct _Entry {
	size_t idx;
	unsigned char* word;
	size_t len;
	size_t prev_idx;
	unsigned char append;
} Entry;

typedef struct _TreeNode {
	size_t idx;
	unsigned char c;
	struct _TreeNode* child[SYMCOUNT];
} TreeNode;

const size_t symbolcnt = SYMCOUNT;

TreeNode* initnode(TreeNode* node, size_t idx, unsigned char c)
{
	size_t i;
	node->idx = idx;
	node->c = c;
	for (i = 0; i < symbolcnt; i++)
		node->child[i] = NULL;
	return node;
}

void insertdict(Entry* dict, size_t idx, size_t len, unsigned char* word, size_t j)
{
	size_t i;
	dict[idx].idx = idx;
	dict[idx].len = len;
	dict[idx].word = (unsigned char*)malloc(sizeof(unsigned char) * len + 1);
	for (i = 0; i < len; i++)
		dict[idx].word[i] = word[i];
	dict[idx].word[i] = 0;
	dict[idx].prev_idx = j;
	dict[idx].append = word[len - 1];
}

typedef struct _BitStream {
	unsigned char* base;
	unsigned char* ptr;
	unsigned char offset;
	size_t capacity;
} BitStream;

void bsshift1(BitStream* bs)
{
	/* shift the offset of bitstream bs */
	bs->offset++;
	if (bs->offset % (sizeof(unsigned char) * 8) == 0) {
		bs->ptr++;
		bs->offset = 0;
	}
}

void bswriteb(BitStream* bs, unsigned char b)
{
	/* write the least significant bit of b into the bitstrem bs (LSB) */
	*(bs->ptr) &= ((unsigned char)0xff >> (8 - bs->offset));
	if (b & 1)
		* (bs->ptr) |= (1 << bs->offset);
	bsshift1(bs);
}

unsigned char bsgetb(BitStream* bs)
{
	/* get the LSB of the bitstream bs */
	unsigned char bit = (*(bs->ptr) & (1 << bs->offset)) >> bs->offset;
	bsshift1(bs);
	return bit;
}

void err(const char * err)
{
	printf("[ERROR MESSAGE]: %s", err);
	fflush(stdout);
	exit(-1);
}

BitStream* bsnew(unsigned char* buffer, size_t cap)
{
	BitStream* bs = (BitStream*)malloc(sizeof(BitStream));
	if (!bs) err("MALLOC FAILED!");
	bs->base = buffer;
	bs->ptr = buffer;
	bs->capacity = cap;
	bs->offset = 0;
	return bs;
}

